<!DOCTYPE html>
<html lang="en" style="">
<head>
	<title>1.5-Parameter-Rule | PhalApi - A light-weight PHP framework for API</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
	<meta name="description" content="PhalApiis A light-weight PHP framework for API!">
	<meta name="keywords" content="PhalApi,phalapi,phalapi API develop,backend framework,restful,web services,saas,microservice,API framework,open API framework,PHP API framework,php web framework">
	<meta name="author" content="dogstar">

	<link rel="stylesheet" type="text/css" href="./../..//css/screen.css?20150211" />
</head>

<body>
<a href="https://github.com/phalapi/phalapi">
	<img alt="Fork me on GitHub" data-canonical-src="http://7xslqv.com1.z0.glb.clouddn.com/images/2/2d/9e69c0ebaff22a24e241a0244532e.png" src="http://7xslqv.com1.z0.glb.clouddn.com/images/2/2d/9e69c0ebaff22a24e241a0244532e.png" style="position: absolute; top: 0; right: 0; border: 0;">
</a>

<!-- 最顶部的语言(S) -->
<div class="grid-wrapper navbar desktop-only">
	<div class="grid">
		<div class="grid__cell">
			<ul id="language-switchers" class="navbar__links navbar--left">
                <li class="menu-item"><a title="PhalApi官方网站中文版" href="/" class="menu-item__link">Chinese</a></li>
				<li class="menu-item"><a title="English version of PhalApi website" href="/wikis/en/" class="menu-item__link">English</a></li>
			</ul>
			<ul id="util-menu" class="navbar__links navbar--right navbar--vertical-separator">
				<li class="menu-item"><a href="#" class="menu-item__link contact-us-spec">Welcome Here!</a></li>
			</ul>
		</div>
	</div>
</div>
<!-- 最顶部的语言(E) -->

<!-- 顶部导航菜单(S) -->
<div class="grid-wrapper desktop-only">
	<div class="grid">
		<div class="grid__cell">
			<div class="header__header-wrapper">
				<a title="PhalApi" href="http://www.phalapi.net" class="header__logo"><img src="http://webtools.qiniudn.com/master-LOGO-20150410_33.jpg" id="tw-logo" alt="PhalApi"></a>
				<ul id="main-menu" class="header__menu">
					<li class="menu-item"><a href="http://qa.phalapi.net/" class="menu-item__link insights-spec" target="_blank">Community</a></li>
					<li class="menu-item"><a href="https://github.com/phalapi/phalapi" class="menu-item__link insights-spec" target="_blank">Download</a></li>
					<li class="menu-item"><a href="/wikis/en/" class="menu-item__link events-spec" target="_blank">Wikis</a></li>
    				<li class="menu-item"><a href="/docs_en/" class="menu-item__link events-spec" target="_blank">Classes docs</a></li>
					<li class="menu-item"><a href="http://demo.phalapi.net/" class="menu-item__link products-spec" target="_blank">Demo</a></li>
					<li class="menu-item"><a href="/about.html" class="menu-item__link about-us-spec" target="_blank">About us</a></li>
				</ul>
			</div>
		</div>
	</div>
</div>
<!-- 顶部导航菜单(E) -->


    <div class="grid-wrapper">
        <div class="grid">
            <div class="grid__cell">
                <h2>1.5 Parameter Rule</h2>
<p>This part will be a little long, but it will be very helpful.  </p>
<h3>1.5.1 Parse client params</h3>
<p>Parameter is important for backend APIs but also for client request.  </p>
<p>That's why we hope to simplify backend APIs development in getting client params, checking params, verifying params and writting API docs. On the other hand, client can post params with more freedom.   </p>
<p>So in PhalApi, we introuce the concept of <strong>parsing client params</strong>, i.e. auto getting and verifying client params by rule configs.   </p>
<p>What developers need to do is just writting rule config, and PhalApi will do the rest automatically. Let's explore more detail.   </p>
<h3>1.5.2 Rule configs</h3>
<p>Developers who are from Yii should by familiar with rule configs. Those who have not used Yii before can handle thess configs in a short time. With time moving on, you can find these configs follow the format as below.  </p>
<pre><code>array(
    'backend param name' =&gt; array('name' =&gt; 'API param name', 'type' =&gt; 'param type', 'default' =&gt; 'param default value', ...),
    ... ...
)</code></pre>
<h3>1.5.3 Example</h3>
<h4>(1) A simple example</h4>
<p>Let's take login API as example. Assume that we need to provide a login API service, which will allow user to login by providing his/her username and password.  </p>
<pre><code>&lt;?php

class Api_User extends PhalApi_Api
{
    public function getRules()
    {
        return array(
            'login' =&gt; array(
                'username' =&gt; array('name' =&gt; 'username'),
                'password' =&gt; array('name' =&gt; 'password'),
            ),
        );
    }

    public function login()
    {
        return array('username' =&gt; $this-&gt;username, 'password' =&gt; $this-&gt;password);
    }                                    
}</code></pre>
<p>Then we can request it like this:  </p>
<pre><code>/?service=User.Login&amp;username=test&amp;password=123456</code></pre>
<p>and it will reponse:  </p>
<pre><code>{"ret":0,"data":{"username":"test","password":"123456"},"msg":""}</code></pre>
<p>All rule configs should located at <code>getRules()</code> method. In this case, there are tow params for <code>login</code> service. Then develop can get the client param by class member property, such as <code>$this-&gt;username</code>, <code>$this-&gt;password</code>.  </p>
<h4>(2)A full example</h4>
<p>We just only define tow simple params. However, we need to do more other things before we get the param from client, such as verifying whether required or not, max length, min/max value limitiation etc.  </p>
<p>Let's continue to complete the rule configs above. The params <code>username</code> and <code>password</code> should be required, and the min length of <code>password</code> should be greater than 6.   </p>
<pre><code>'login' =&gt; array(
   'username' =&gt; array('name' =&gt; 'username', 'require' =&gt; true),
   'password' =&gt; array('name' =&gt; 'password', 'require' =&gt; true, 'min' =&gt; 6),
),</code></pre>
<p>Try to request again without any params. When we request <code>/?service=User.Login</code>, we will get:  </p>
<pre><code>{"ret":400,"data":[],"msg":"Illegal Param: wrong param: username"}</code></pre>
<p>When we request with wrong length of password like <code>/?service=User.Login&amp;username=test&amp;password=123</code>, we will get:  </p>
<pre><code>{"ret":400,"data":[],"msg":"Illegal Param: password.len should &gt;= 6, but now password.len = 3"}</code></pre>
<p>Look! PhalApi do many things automatically, what we need to do is just a little config and then enjoy it!  </p>
<h3>4.5.4 Three kinds of params</h3>
<h4>(1)System params</h4>
<p>Currently, there is only one system param, i.e. <code>service</code>. The param <code>service</code> is a string, which looks like <code>XXX.XXX</code>, determining which API service client will call.  </p>
<p>Here are some examples.  </p>
<pre><code># Recommend example
/?service=User.GetBaseInfo

# Right example(start with lower case letter)
/?service=user.getBaseInfo(method name is all lower case letter. NOTE: class name just can start with lower case letter, the rest should keep the same with class file name, or lead to a NOT FOUND exception)  
/?service=user.getbaseinfo

# Illegal service(missing method name)
/?service=User
# Illegal service(missing dot between class name and method name)
/?service=UserGetBaseInfo
# Illegal service(only support split with dot now)
/?service=User|GetBaseInfo</code></pre>
<h4>(2)Application params</h4>
<p>Application params are common client params in one API project. All thess application params should be located at <code>apiCommonRules</code> in the config file <code>./Config/app.php</code>. For example, if we need a required <code>sign</code> param, and a NOT required <code>version</code> param for all APIS, we can edit the <code>apiCommonRules</code> and add the code as below.   </p>
<pre><code>//$vim ./Config/app.php
&lt;?php

return array(
    /**
     * API common param rules
     */
    'apiCommonRules' =&gt; array(
        // a required ```sign``` param
        'sign' =&gt; array(
            'name' =&gt; 'sign', 'require' =&gt; true,
        ),
        // a NOT required ```version``` param
        'version' =&gt; array(
            'name' =&gt; 'version', 'default' =&gt; '', 
        ),
    ),

    ... ...</code></pre>
<h4>(3)API params</h4>
<p>At last, we can define sepecified client params for each API service. In addition,  in order to reuse rule configs in the same API class, we can use <code>*</code> rules, which are common rules only in one API class. For example, we add a reqiured <code>code</code> param, which's length is 4, for all User APIs.  </p>
<pre><code>    public function getRules()
    {
        return array(
            '*' =&gt; array(
                'code' =&gt; array('name' =&gt; 'code', 'require' =&gt; true, 'min' =&gt; 4, 'max' =&gt; 4),
                ),
            'login' =&gt; array(
                'username' =&gt; array('name' =&gt; 'username', 'require' =&gt; true),
                'password' =&gt; array('name' =&gt; 'password', 'require' =&gt; true, 'min' =&gt; 6),
            ),
        );
    }</code></pre>
<p>After we configure application common params, API common params and sepcecified API params, client can request the <code>login</code> API service as below.  </p>
<pre><code>/?service=User.login&amp;sign=77f81c17d512302383e5f26b99dae4d9&amp;username=test&amp;password=123456&amp;version=1.3.6&amp;code=abcd</code></pre>
<blockquote>
<p>NOTE: The indexes of rule configs in API class are case-insensitive.  </p>
</blockquote>
<p>In summary, there are tow kinds of params in API class, i.e. <strong>API common params</strong> and <strong>sepcecified API params</strong>. The former is represent with <code>*</code>, while the latter is represent with the name of method.  </p>
<h4>(4) Params priority</h4>
<p>When one rule config for the same param repeat in application params, API common params and sepcecified API params, the latter rule will cover the former one. That's to say, sepcecified API params rule will take replace of common params rule to ensure developers can custom their rules by need.  </p>
<p>In short, the priority of parameter rule is as below(as you expect):  </p>
<ul>
<li>
<ol>
<li>HIGHEST, sepcecified API parameter rule</li>
</ol>
</li>
<li>
<ol>
<li>common API parameter rule</li>
</ol>
</li>
<li>
<ol>
<li>application parameter rule  </li>
</ol>
</li>
<li>
<ol>
<li>LOWEST, system parameter rule(only one param, i.e. <code>service</code>)  </li>
</ol>
</li>
</ul>
<h3>4.5.5 Online API detail documents(auto generated)</h3>
<p>For the sake of convenience to check all the client params fast, PhalApi provides online API detail documents. They are auto generated by the parameter rules above.  Vist the follow URI in the bowser:  </p>
<pre><code>/demo/checkApiParams.php?service=Default.Index</code></pre>
<p>And you can see:<br />
<img src="https://camo.githubusercontent.com/8829812d88782945976414d60319933ebcefa1d2/687474703a2f2f6769742e6f736368696e612e6e65742f75706c6f6164732f696d616765732f323031372f303231382f3233303334375f37373461663063325f3132313032362e706e67" alt="" />  </p>
<p>Thess API docs can be also provided to client developers during project development.  </p>
<h4>Self-description data</h4>
<p>It is worth to mention that the parameter rules we define actually are self-description data. It means the code of rules reflect related properties of params.  </p>
<h3>4.5.6 All kinds of rule types</h3>
<table>
<thead>
<tr>
<th>Param Type(type)</th>
<th>IS Required(require)</th>
<th>Defaul Value(default)</th>
<th>Min&amp;Max Value(min&amp;max)</th>
<th>MORE</th>
</tr>
</thead>
<tbody>
<tr>
<td>string</td>
<td>true/false, default is false</td>
<td>should be a string</td>
<td>Optional</td>
<td><code>regex</code> index defines the regex need to be matched, and <code>format</code> index defines charaset, such as utf8, gbk, gb2312 etc.</td>
</tr>
<tr>
<td>int</td>
<td>true/false, default is false</td>
<td>should be a integer</td>
<td>Optional</td>
<td>---</td>
</tr>
<tr>
<td>float</td>
<td>true/false, default is false</td>
<td>should be a float number</td>
<td>Optional</td>
<td>---</td>
</tr>
<tr>
<td>boolean</td>
<td>true/false, default is false</td>
<td>true/false</td>
<td>---</td>
<td>It will treat <code>ok, true, success, on, yes, 1</code> as TRUE</td>
</tr>
<tr>
<td>date</td>
<td>true/false, default is false</td>
<td>translate with the format</td>
<td>Optional, only need to check while the format is <code>timestamp</code>|It will turns into timestamp while the format is <code>timestamp</code></td>
</tr>
<tr>
<td>array</td>
<td>true/false, default is false</td>
<td>should be an array, or try to trun into an array if NOT</td>
<td>Optional, check array count</td>
<td>It will call <code>explode()</code> with format <code>separator</code> if <code>format</code> is <code>explode</code>, and will call <code>json_decode()</code> if <code>format</code> is <code>json</code></td>
</tr>
<tr>
<td>enum</td>
<td>true/false, default is false</td>
<td>should inside the <code>range</code>|---|Required，use <code>range</code> range to sepecify enum range</td>
</tr>
<tr>
<td>file</td>
<td>true/false, default is false</td>
<td>should be an array</td>
<td><code>min</code> nad <code>max</code> are represent the size of upload file|<code>range</code> index is represent for the types of upload file allowing to post, while <code>ext</code> will filter the external name</td>
</tr>
<tr>
<td>callable</td>
<td>true/false, default is false</td>
<td>---</td>
<td>---</td>
<td><code>callback</code> can set callback function with <code>params</code> as the third param, the first is param value, the second is current rule config</td>
</tr>
</tbody>
</table>
<blockquote>
<p>NOTE: You can add <code>desc</code> index for all of the rule types, which will be displayed in the section <code>Desc</code> in online API detail docs.  </p>
</blockquote>
<p>Let's study each rule type with examples one by one.  </p>
<h4>(1)Rule type: string</h4>
<p>When a rule config is defined without <code>type</code>, it will be <code>string</code> in default. A full config for string type is:  </p>
<pre><code>array('name' =&gt; 'username', 'type' =&gt; 'string', 'require' =&gt; true, 'default' =&gt; 'nobody', 'min' =&gt; 1, 'max' =&gt; 10)</code></pre>
<p>We use <code>'type' =&gt; 'string'</code> to sepecify username is a string.  </p>
<p>Then if anyone post a too much long username, such as <code>&amp;username=alonglonglonglongname</code>, he will get an exception as returned.  </p>
<pre><code>{"ret":400,"data":[],"msg":"Illegal Param: username.len should &lt;= 10, but now username.len = 21"}</code></pre>
<p>It there will be some special(other charset) in username, we can add <code>format</code> index to sepecify which charset we use.  </p>
<pre><code>array('name' =&gt; 'username', 'type' =&gt; 'string','format' =&gt; 'utf8', 'min' =&gt; 1, 'max' =&gt; 10)</code></pre>
<p>We can add more powerful verification with <code>regex</code> index. Take email for example.  </p>
<pre><code>'email' =&gt; array(
    'name' =&gt; 'email',
    'require' =&gt; true,
    'min' =&gt; '1',
    'regex' =&gt; "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i",
    'desc' =&gt; 'You should post a correct email address',
),</code></pre>
<h4>(2)Rule type: int</h4>
<p>Usually, we can configure <code>id</code> param for database tables as below.  </p>
<pre><code>array('name' =&gt; 'id', 'type' =&gt; 'int', 'require' =&gt; true, 'min' =&gt; 1 )</code></pre>
<blockquote>
<p>NOTE: <code>id</code> should be in [<code>min</code>, <code>max</code>).  </p>
</blockquote>
<p>If client post an <code>id</code> beyond the range, such as <code>&amp;id=0</code>, it will fail.  </p>
<pre><code>{"ret":400,"data":[],"msg":"Illegal Param: id should &gt;= 1, but now id = 0"}</code></pre>
<h4>(3)Rule type: float</h4>
<p>See <code>int</code> in above.  </p>
<h4>(4)Rule type: boolean</h4>
<p>PhalApi will treat strings like <code>ok, true, success, on, yes</code> as boolean TRUE, any other strings PHP will parse as TRUE will also turn into TRUE. For example, we can add one more param for <code>login</code> service.  </p>
<pre><code>array('name' =&gt; 'isRememberMe', 'type' =&gt; 'boolean', 'default' =&gt; true)</code></pre>
<h4>(4)Rule type: date</h4>
<p>We can post a date as we want.  </p>
<pre><code>array('name' =&gt; 'registerData', 'type' =&gt; 'date')</code></pre>
<p>When client post <code>&amp;risterData=2015-01-31 10:00:00</code>, we will get <code>2015-01-31 10:00:00</code> in API.  </p>
<p>If we want a timestamp instead of a string, we can configure as below:  </p>
<pre><code>array('name' =&gt; 'registerData', 'type' =&gt; 'date', 'format' =&gt; 'timestamp')</code></pre>
<p>At last, we will get 1422669600, which is equals to <code>strtotime('2015-01-31 10:00:00')</code>.  </p>
<h4>(5)Rule type: array</h4>
<p>Usually, client need to post serveral items in one request. That's why we need <code>array</code> type. For example:  </p>
<pre><code>array('name' =&gt; 'uids', 'type' =&gt; 'array', 'format' =&gt; 'explode', 'separator' =&gt; ',')</code></pre>
<p>Then params <code>&amp;uids=1,2,3</code> will be turned into:  </p>
<pre><code>array ( 0 =&gt; '1', 1 =&gt; '2', 2 =&gt; '3', )</code></pre>
<p>If client want to post params in JSON, we need to set <code>format</code> index with <code>json</code>.  </p>
<pre><code>array('name' =&gt; 'params', 'type' =&gt; 'array', 'format' =&gt; 'json')</code></pre>
<p>Then params <code>&amp;params={"username":"test","password":"123456"}</code> will be turned into:  </p>
<pre><code>array ( 'username' =&gt; 'test', 'password' =&gt; '123456', )</code></pre>
<p>Please note that, if we use array type but without format, it will be turned into an array, which contains one element. For example, <code>&amp;name=test</code> will become <code>array(0 =&gt; 'test')</code>.  </p>
<h4>(7)Rule type: enum</h4>
<p>You can use this enum type when you need to limit the range of parameters. Take sex for example.  </p>
<pre><code>array('name' =&gt; 'sex', 'type' =&gt; 'enum', 'range' =&gt; array('female', 'male'))</code></pre>
<p>We only allow female/male for <code>sex</code> param. Therefore, any other strings will be treated as illegal param. Let's try to post <code>&amp;sex=unknow</code>. No doubt that we will get something like this.    </p>
<pre><code>{"ret":400,"data":[],"msg":"Illegal Param: sex should be in female\/male, but now sex = unknow"}</code></pre>
<p>Please keep in mind, it's better to use string, NOT int/float, for <code>range</code>.<br />
Because in generally, what we get from GET/POST method are strings, not int/float, otherwise will lead to  unexpected result. Here is an example show how wrong range occur a bug.  </p>
<pre><code>// Assume client post &amp;type=N

// rule config as below
array('name' =&gt; 'type', 'type' =&gt; 'enum', 'range' =&gt; array(0, 1, 2))

// wrong result
var_dump(in_array('N', array(0, 1, 2))); // it prints true, since 'N' == 0 in PHP</code></pre>
<p>To avoid this kind bug, we should configure as below.  </p>
<pre><code>// rule config (use STRING, not integer)
array('name' =&gt; '&amp;type', 'type' =&gt; 'enum', 'range' =&gt; array(`0`, `1`, `2`))</code></pre>
<h4>(8)Rule type: file</h4>
<p>When we want to receive files from client, we can use type <code>file</code>. Let's take an exmaple.  </p>
<pre><code>array(
    'name' =&gt; 'upfile', 
    'type' =&gt; 'file', 
    'min' =&gt; 0, 
    'max' =&gt; 1024 * 1024, 
    'range' =&gt; array('image/jpeg', 'image/png') , 
    'ext' =&gt; array('jpeg', 'png')
)</code></pre>
<p>These config means that, the size of file should be greater than 0B, and less than 1MB, client only can post jpeg/png files in form filed <code>upfile</code>, and the external file name should be jpeg/png. If client upload successfully, we will get <code>$_FILES["upfile"]</code>.  </p>
<pre><code>array(
     'name' =&gt; '',
     'type' =&gt; '',
     'size' =&gt; '',
     'tmp_name' =&gt; '',
)</code></pre>
<p>More information about <code>$_FILE</code>, please visit <a href="http://php.net/manual/en/reserved.variables.files.php">$_FILE</a>.  </p>
<p>There are some more examples about <code>ext</code>.  </p>
<pre><code>// single external name in array
'ext' =&gt; array('jpg')

// single external name in string
'ext' =&gt; 'jpg'

// multi external names in array
'ext' =&gt; array('jpg', 'jpeg', 'png', 'bmp')

// multi external names in string, split with comma
'ext' =&gt; 'jpg,jpeg,png,bmp'</code></pre>
<h4>(9)Rule type: callable</h4>
<p>If we want to verify and parse the client params by ourself, we can use type <code>callable</code>. Let's try to check the version param with <code>Common_MyVersion::formatVersion()</code>.  </p>
<pre><code>array('name' =&gt; 'version', 'type' =&gt; 'callable', 'callback' =&gt; array('Common_MyVersion', 'formatVersion'))</code></pre>
<p>Then PhalApi will call <code>Common_MyVersion::formatVersion()</code> client post a version. And we can do anything in <code>Common_MyVersion::formatVersion()</code> as we want.  </p>
<pre><code>// create an new class

class Common_MyVersion {

    public static function formatVersion($value, $rule) {
        if (count(explode('.', $value)) &lt; 3) {
            throw new PhalApi_Exception_BadRequest('Illegal version');
        }
    }
}</code></pre>
<blockquote>
<p>NOTE: the first param <code>$value</code> is the origin value from client param, the second param <code>$rule</code> is our rule config as above, the third param(OPTIONAL) equals to the <code>params</code> index in <code>$rule</code>.  </p>
</blockquote>
<h3>4.5.7 The principle to design parameter rule</h3>
<h4>(1) Free to map client param name with backend member name</h4>
<p>In some case, backend would like to name variable by Camel-Case, while client would prefer name parameters with underline. That's why we need tow name in rule config, one is for backend, anther one is for client.  </p>
<pre><code>array(
    'isRememberMe' =&gt; array('name' =&gt; 'is_remember_me', 'type' =&gt; 'boolean', 'default' =&gt; true),
)</code></pre>
<p>Here, client post with <code>&amp;is_remember_me=1</code>, and backend get with <code>$this-&gt;isRememberMe</code>. Perfect cooporation between backend and frontend? AhA~ I think so.  </p>
<p>We can also make a shorter name for client to save network traffic.  </p>
<pre><code>array(
    'isRememberMe' =&gt; array('name' =&gt; 're', 'type' =&gt; 'boolean', 'default' =&gt; true),
)</code></pre>
<p>Then client can post with <code>&amp;re=1</code> instead.  </p>
<h4>(2)Returning exception</h4>
<p>PhalApi will return an exception, which's code is usually <code>4xx</code>, while client post illegal params. This can remind client they post wrong params.  </p>
<h3>4.5.8 Extend your rule type</h3>
<p>When PhalApi provides parameter rules that do not meet your need, you can extend the <code>PhalApi_Request_Formatter</code> interface to customize your own type, in addition to using the <code>callable</code> type.  </p>
<p>There are tow more step before you use your own type.  </p>
<ul>
<li>
<ol>
<li>Extend and implement the <code>PhalApi_Request_Formatter</code> interface.</li>
</ol>
</li>
<li>
<ol>
<li>Register the new type in DI.  </li>
</ol>
</li>
</ul>
<p>Let's take <code>email</code> type for example.  </p>
<p>Firstly, we need to implement interface <code>PhalApi_Request_Formatter</code>.  </p>
<pre><code>&lt;?php

class Common_MyFormatter_Email implements PhalApi_Request_Formatter {

    public function parse($value, $rule) {
        if (!preg_match('/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/', $value)) {
            throw new PhalApi_Exception_BadRequest('Illegal email');
        }

        return $value;
    }
}  </code></pre>
<p>Secondly, register it into DI.  </p>
<pre><code>DI()-&gt;_formatterEmail = 'Common_MyFormatter_Email';</code></pre>
<blockquote>
<p>NOTE: The name of service should follow <code>DI()-&gt;_formatter + type name(first letter is upper case, the rest is lower case)</code>.  </p>
</blockquote>
<p>At last, we can use our new type <code>email</code> now as below.  </p>
<pre><code>array('name' =&gt; 'user_email', 'type' =&gt; 'email')</code></pre>
<p>There are all the formatting service by now.  </p>
<ul>
<li>_formatterArray </li>
<li>_formatterBoolean </li>
<li>_formatterCallable </li>
<li>_formatterDate </li>
<li>_formatterEnum </li>
<li>_formatterFile </li>
<li>_formatterFloat </li>
<li>_formatterInt </li>
<li>_formatterString </li>
</ul>
            </div>
        </div>
    </div>
    
 <!-- 广告位 -->
<!--
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7qnay5.com1.z0.glb.clouddn.com/走向开源的第一年%20-%20PhalApi%202015年度开源总结%20-%20官方出品%20-%2020151214.pdf" target="blank"><img width="950" height="100" src="http://7qnay5.com1.z0.glb.clouddn.com/PhalApi20151213-2.jpg"></a>
		<a href="http://qa.phalapi.net" target="blank"><img width="950" height="100" src="http://7qnay5.com1.z0.glb.clouddn.com/qa_ad_20150615.jpg"></a>
	</p>
</div>
-->

<!-- footer(S) -->
<div class="grid-wrapper footer">
	<div id="footer" class="grid">	

		<div class="grid__cell unit-1-2--lap">
			<h3><img src="http://webtools.qiniudn.com/master-LOGO-20150410_50.jpg" height="50"></h3>
            <p>
            <font size="3px;">PhalApi is a light-weight PHP framework for API.<br/>
                We try to keep PhalApi as stuip simple as possible!
            </font>
			</p>
			<p align="left">
				<font size="2px">&copy;2015-2016 PhalApi All Rights Reserved. 粤ICP备15028808号</font>
				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
			</p>
		</div>	

		<div class="grid__cell unit-1-2--lap">
			<h3>Thanks!</h3>

			<div class="nav">
				<ul class="footer__nav">
					<li class="menu-item"><a href="http://www.oschina.net/" class="menu-item__link" target="_blank">Open Source China</a></li>
					<li class="menu-item"><a href="http://www.phalconphp.com/en/" class="menu-item__link" target="_blank">Phalcon</a></li>
					<li class="menu-item"><a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" class="menu-item__link" target="_blank">PHPUnit</a></li>
					<li class="menu-item"><a href="http://www.thoughtworks.com/cn/" class="menu-item__link" target="_blank">ThoughtWorks</a></li>
				</ul>
			</div>

            <div id="perspectives">
                <div class="email-signup">
                    <strong><a href="https://auth.alipay.com/login/index.htm" target="_blank">Alipay&nbsp;</a>Donate: </strong>chanzonghuang@gmail.com
                </div>
            </div>

			<p>
				<!-- JiaThis Button BEGIN -->
				<div id="ckepop">
				<span class="jiathis_txt">Share: </span>
				<a class="jiathis_button_tsina">Weibo</a>
				<a href="http://www.jiathis.com/share" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank">More</a>
				<a class="jiathis_counter_style"></a>
				</div>
				<script type="text/javascript" src="http://v2.jiathis.com/code/jia.js" charset="utf-8"></script>
				<!-- JiaThis Button END -->
				
			</p>
		</div>
	</div>
</div>
<!-- footer(E) -->

</body>

<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1254743218'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "w.cnzz.com/q_stat.php%3Fid%3D1254743218' type='text/javascript'%3E%3C/script%3E"));</script>

</html>
